package ucd.csi.comp30220.fall2011.oteop.util;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;

public class ServiceFinder {
    
    private static final long SLEEP = 100;
    
    public static EndPoint findService(
            final String type, final String subType, final String name, final long timeout) throws Exception 
    {
        final ServiceInfo[] serviceInfo = new ServiceInfo[1];
        final JmDNS jmDNS = JmDNS.create();
        
        new Thread(new Runnable() {
            public void run() {
                try {
                    jmDNS.addServiceListener(
                        type,
                        new ServiceListener() {
                            public void serviceAdded(ServiceEvent event) {
                                // Not spectacularly interesting, we need it to be resolved
                            }
                            public void serviceRemoved(ServiceEvent event) {
                                // Not interested
                            }
                            public void serviceResolved(ServiceEvent event) {
                                if (subType.equals(event.getInfo().getSubtype())) {
                                    if (name == null || name.equals(event.getInfo().getName())) {
                                        serviceInfo[0] = event.getInfo();
                                    }
                                }
                            }
                        });
                    
                    // Belt and braces, but I don't trust JmDNS
                    for (long time = 0; serviceInfo[0] == null && time < timeout; time += SLEEP) {
                        ServiceInfo[] infos = jmDNS.list(type);
                        for (ServiceInfo si : infos) {
                            if (subType.equals(si.getSubtype())) {
                                if (name == null || name.equals(si.getName())) {
                                    serviceInfo[0] = si;
                                    break;
                                }
                            }
                        }
                        Thread.sleep(SLEEP);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        for (long time = 0; serviceInfo[0] == null && time < timeout; time += SLEEP) 
            Thread.sleep(SLEEP);
        
        if (serviceInfo[0] == null)
            return null;
        
        if (name == null)
            return new EndPoint(new String(serviceInfo[0].getTextBytes()), serviceInfo[0].getPort());
            
        return new EndPoint(serviceInfo[0].getHostAddresses()[0], serviceInfo[0].getPort());
    }
}
